#pragma once

#include "my_defs.h"
#include "my_rbtree.h"
#include "my_queue.h"

typedef int64_t (*my_slru_item_size_get_handler_t)(void *key, void *val);

typedef void (*my_slru_item_free_handler_t)(void *key, void *val);

typedef int (*my_slru_item_key_cmp_t)(void *key1, void *key2);

typedef struct {
    int64_t                             nlist;
    int64_t                             max_item;
    // support total key + val size limit.
    int64_t                             max_bytes;
    my_slru_item_size_get_handler_t     item_size_get_handler;
    my_slru_item_free_handler_t         free_handler;
    my_slru_item_key_cmp_t              key_cmp_handler;

    my_queue_t                          *lists;
    int64_t                             *lists_bytes;
    int64_t                             *lists_n;

    my_rbtree_t                         tree;
    my_rbtree_node_t                    sentinel;
} my_slru_t;


my_slru_t *my_slru_create(
    int64_t nlist,
    int64_t max_item,
    int64_t max_bytes,
    my_slru_item_size_get_handler_t item_size_get_handler,
    my_slru_item_free_handler_t free_handler,
    my_slru_item_key_cmp_t      key_cmp_handler);

void my_slru_destroy(my_slru_t *slru);

void *my_slru_get(my_slru_t *slru, void *key, my_bool_t *found);

void my_slru_put(my_slru_t *slru, void *key, void *val);

// remove and free cache item.
my_bool_t my_slru_remove(my_slru_t *slru, void *key);


// will not increase the heat of the object
void *my_slru_ge(my_slru_t *slru, void *key, my_bool_t *found);

// will not increase the heat of the object
void *my_slru_le(my_slru_t *slru, void *key, my_bool_t *found);